#!/usr/bin/env python3
"""Compose V2 enhanced video - with more real V9 dynamic footage"""
import os, subprocess, re, sys

BASE = r'E:\集群文件夹\factory_os\short_video_real_data_pipeline\phase4b_90s_formal_sample\v22_kimi_claude_loop\full_story_douyin_video'
FFMPEG = r'D:\AI_WORKSPACE\tools\ffmpeg\ffmpeg.exe'
CLIPS = os.path.join(BASE, '05_clips')
AUDIO = os.path.join(BASE, '05_audio_mix', 'v2', 'final_audio_mix_v2.wav')
SUBS = os.path.join(BASE, '04_subtitles', 'v2', 'captions_final_v2.ass')
VIDEO_OUT = os.path.join(BASE, '06_video', 'claude_code_self_evolving_full_story_douyin_v2.mp4')

# ENHANCED scene order with V9 real footage inserted
# V9_dyn clips are real ComfyUI rendered content (not programmatic)
SCENE_ORDER = [
    'title',           # 3.5s - title card (keep)
    'punch',           # 3s - hook montage (keep)
    'recording_fail',  # 4s - recording fail (keep - story essential)
    'five_fails',      # 4s - five fails (keep)
    'ai_drift',        # 4s - AI drift (keep)
    'chatgpt_fix',     # 4s - ChatGPT fix suggestion (keep)
    'python_render',   # 4s - Python rendering (keep)
    'multi_agent',     # 4s - multi-agent cards (keep)
    'log_lines',       # 3s - log lines (keep)
    # Insert V9 real footage before Kimi intro to show actual rendering
    'v9_dyn_1',        # 5s - REAL V9 rendering footage
    'kimi_intro',      # 4s - Kimi intro card
    # Extended score area with V9 background
    'score_bars',      # 6s - score progression bars
    'v9_dyn_2',        # 6s - REAL V9 rendering continues behind score
    'v9_peak',         # 3s - V9 peak at 92
    'v9_dyn_3',        # 5s - REAL V9 peak footage
    'v10_crash',       # 5s - V10 crash animation
    'v11_recovery',    # 4s - V11 recovery
    'lesson',          # 3s - lesson learned
    'rollback',        # 3s - rollback decision
    'review_portal',   # 4s - Review Portal
    'http_verify',     # 4s - HTTP 200 verification
    'summary',         # 4s - summary statistics
    'final_montage',   # 4s - final montage
    'end_card',        # 7.5s - end card
]

def run_cwd(cmd, cwd, desc):
    print(f"\n--- {desc} ---")
    r = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, encoding='utf-8', errors='replace')
    if r.returncode != 0:
        err = r.stderr[-400:] if len(r.stderr) > 400 else r.stderr
        print(f"  WARNING: {err}")
        return False
    print(f"  OK")
    return True

def get_dur(f):
    """Get duration of media file"""
    r = subprocess.run([FFMPEG, '-i', f], capture_output=True, text=True, encoding='utf-8', errors='replace')
    m = re.search(r'Duration: (\d+):(\d+):(\d+\.\d+)', r.stderr)
    if m: return int(m.group(1))*3600 + int(m.group(2))*60 + float(m.group(3))
    return 0

# Verify all scenes exist
missing = [s for s in SCENE_ORDER if not os.path.exists(os.path.join(CLIPS, s+'.mp4'))]
if missing:
    print(f"ERROR: Missing clips: {missing}")
    sys.exit(1)
print(f"All {len(SCENE_ORDER)} clips OK")

# Create concat file
concat_file = os.path.join(CLIPS, 'c_v2.txt')
with open(concat_file, 'w', encoding='utf-8') as f:
    for s in SCENE_ORDER:
        f.write(f"file '{s}.mp4'\n")

# Concatenate scenes
joined = os.path.join(CLIPS, '_j_v2.mp4')
success = run_cwd([FFMPEG, '-y', '-f', 'concat', '-safe', '0', '-i', 'c_v2.txt',
         '-c', 'copy', '_j_v2.mp4'], CLIPS, "Concatenate scenes")
if not success or not os.path.exists(joined):
    print("FAIL at concat")
    sys.exit(1)

vdur = get_dur(joined)
adur = get_dur(AUDIO)
print(f"\nVideo duration: {vdur:.1f}s | Audio duration: {adur:.1f}s")

# Pad video if shorter than audio
padded = joined
if adur > vdur + 0.5:
    pad_dur = round(adur - vdur, 1)
    print(f"Need to pad video by {pad_dur:.1f}s")
    padded = os.path.join(CLIPS, '_p_v2.mp4')
    run_cwd([FFMPEG, '-y', '-i', joined,
             '-vf', f'tpad=stop_mode=clone:stop_duration={pad_dur}',
             '-c:v', 'libx264', '-preset', 'fast', '-crf', '20', '-pix_fmt', 'yuv420p',
             padded], CLIPS, f"Pad +{pad_dur:.1f}s")
elif vdur > adur + 0.5:
    # Video longer than audio - trim
    print(f"Video is {vdur-adur:.1f}s longer than audio, will use -shortest")

# Add audio and create final video
padded_name = os.path.basename(padded)
run_cwd([FFMPEG, '-y', '-i', padded_name, '-i', AUDIO,
         '-c:v', 'libx264', '-preset', 'medium', '-crf', '20',
         '-c:a', 'aac', '-b:a', '192k', '-pix_fmt', 'yuv420p',
         '-movflags', '+faststart', '-shortest',
         VIDEO_OUT],
        CLIPS, "Add audio + encode final")

# Clean temp files
for f in [joined, padded, concat_file]:
    try:
        if os.path.exists(f): os.remove(f)
    except: pass

# Verify output
if os.path.exists(VIDEO_OUT):
    sz = os.path.getsize(VIDEO_OUT) / (1024*1024)
    dur = get_dur(VIDEO_OUT)
    print(f"\n{'='*50}")
    print(f"[OK] V2 ENHANCED VIDEO COMPLETE")
    print(f"{'='*50}")
    print(f"  Path: {VIDEO_OUT}")
    print(f"  Size: {sz:.1f} MB | Duration: {dur:.1f}s")

    # Calculate real footage ratio
    total_dynamic = 5.0 + 6.0 + 5.0  # v9_dyn_1 + v9_dyn_2 + v9_dyn_3
    total_v9 = 33.3  # full V9 extract exists
    ratio = (total_dynamic / dur) * 100 if dur > 0 else 0
    print(f"  V9 dynamic footage: {total_dynamic:.1f}s ({ratio:.0f}%)")
    print(f"  Real rendering clips inserted: 3")
    print(f"\n  Next: Burn subtitles:")
    print(f"    {FFMPEG} -i {VIDEO_OUT} -vf \"ass={SUBS}\" -c:a copy ...")
else:
    print("\n[FAIL] Output file not created")
